from abc import abstractmethod
import logging
from common.send_requests import sendRequest
from urllib.parse import urljoin
from Model.user import PcUser
from Model.environment import Environment


class Storehouse:
    def __init__(self, env: Environment, puser: PcUser, logger: logging.Logger):
        self.env = env
        self.puser = puser
        print(f"puser: {puser}")
        self.storehouse_dict = {}
        self.logger = logger

    def get_all_storehouse(self):
        url = urljoin(self.env.realmName, "shipping-location-store/search")
        params = {
            "skipCount": 0,
            "maxResultCount": 50
        }
        res = sendRequest(url, "get", headers=self.puser.headers,
                          params=params, msg="仓库查询")
        if res.status_code == 200:
            r = res.json()
            if len(r["items"]) >= 0:
                items = r["items"]
                self.tag = 1
                self.status = f"获取仓库数据成功"

            else:
                self.tag = 0
                self.status = f"未查询到仓库: {items}"
        else:
            self.tag = 0
            self.status = f"查询仓库失败: {res.text}"

        self.logger.info(f"获取仓库数据成功: {res.text}")
        self.logger.info("仓库信息:")
        for info in res.json()["items"]:
            self.storehouse_dict[info["name"]] = {
                "entry": info["entry"],
                "weighbridgeNames": [name for name in info["weighbridgeNames"].split(",")]
            }
        for k, v in self.storehouse_dict.items():
            self.logger.info(f"{k}, {v}")
        self.logger.info("=========================================")


class DispatchingRule:
    # 配送规则
    def __init__(self, env: Environment, puser: PcUser, logger: logging.Logger):
        self.env = env
        self.puser = puser
        self.logger = logger
        print(f"puser: {puser}")
        self.dispatching_rule = {
            # "发货区域": ["收货地址1", "收货地址2", ...]
        }

    def get_receiving_area(self, region_id):
        # 获取收货地址
        url = urljoin(self.env.realmName, f"delivery-rule/{region_id}")
        res = sendRequest(url, "get", headers=self.puser.headers,
                          msg="配送区域查询")
        if res.status_code == 200:
            print(f"配送区域查询成功: {res.text}")
            r = res.json()
            lines = [line["receivingRegion"]["full"] for line in r["lines"]]
        else:
            print(f"配送区域查询失败: {res.text}")
            lines = []
        return lines

    def get_dispatching_rule(self):
        # 获取规则
        url = urljoin(self.env.realmName, "delivery-rule/search")
        params = {
            "skipCount": 0,
            "maxResultCount": 50
        }
        res = sendRequest(url, "get", headers=self.puser.headers,
                          params=params, msg="配送规则查询")
        if res.status_code == 200:

            r = res.json()
            if len(r["items"]) >= 0:
                print(f"配送规则查询成功: {res.text}")
                items = r["items"]
                for i in items:
                    region_id = i["id"]
                    lines = self.get_receiving_area(region_id)
                    self.dispatching_rule[i["shippingRegion"]["full"]] = lines
                    self.status = f"获取配送规则数据成功"
                    for k, v in self.dispatching_rule.items():
                        self.logger.info(f"发货地址：{k}")
                        for n in v:
                            self.logger.info(f"收货地址：{n}")
                    self.logger.info("=======================================")
            else:
                print(f"未查询到配送规则: {items}")
                self.status = f"未查询到配送规则: {items}"
                self.logger.info(f"未查询到配送规则: {items}")
        else:
            print(f"配送规则查询失败: {res.text}")
            self.status = f"查询配送规则失败: {res.text}"
            self.logger.info(f"查询配送规则失败: {res.text}")


class TreatyRule:

    def __init__(self, env: Environment, puser: PcUser, logger: logging.Logger):
        self.code = 0
        self.env = env
        self.puser = puser
        self.logger = logger
        print(f"puser: {puser}")
        self.treaty_rule = {
            # "合约类型": ["合约期限", "合约金额", ...]
        }

    @abstractmethod
    def get_treaty_config(self):
        pass

    @abstractmethod
    def set_treaty_config(self):
        pass

    def get_receiving_area(self):
        pass


class OneLevelTreatyRule(TreatyRule):
    # 一级合约规则

    def get_treaty_config(self):
        # 获取合约配置
        url = urljoin(self.env.realmName, "settings/route-rule-config")
        res = sendRequest(url, "get", headers=self.puser.headers,
                          msg="一级合约配置查询")
        if res.status_code == 200:
            r = res.json()
            print(f"一级合约配置查询成功: {r}")
            self.logger.info(f"一级合约配置查询成功: {r}")
            # 是否启用合同单分配路由
            self.enableContractRoute = r["enableContractRoute"]
            self.logger.info(f"是否启用合同单分配路由: {self.enableContractRoute}")
            # 是否启用自提单分配路由
            self.enableProductRoute = r["enableProductRoute"]
            self.logger.info(f"是否启用自提单分配路由: {self.enableProductRoute}")
            self.code = 1
            self.status = f"获取一级合约配置成功"
        else:
            print(f"一级合约配置查询报错: {res.text}")
            self.logger.info(f"一级合约配置查询报错: {res.text}")
            self.code = 0
            self.status = f"查询一级合约配置报错: {res.text}"

    def set_treaty_config(self, enableContractRoute: bool, enableProductRoute: bool):
        # 设置一级合约配置
        url = urljoin(self.env.realmName, "settings/set-route-rule-config")
        data = {
            # 合约
            "enableContractRoute": enableContractRoute,
            # 自提
            "enableProductRoute": enableProductRoute
        }
        res = sendRequest(
            url, "post", headers=self.puser.headers, js=data, msg="一级合约配置设置")
        if res.status_code == 200:
            print(f"一级合约配置设置成功: {res.text}")
            self.logger.info(f"一级合约配置设置成功: {res.text}")
            self.code = 1
            self.status = f"一级合约配置设置成功"
        else:
            print(f"一级合约配置设置报错: {res.text}")
            self.logger.info(f"一级合约配置设置报错: {res.text}")
            self.code = 0
            self.status = f"一级合约配置设置报错: {res.text}"

    def get_receiving_area(self):
        # 获取收货区域
        url = urljoin(self.env.realmName, "carrier-assign-route-rule/search")
        data = {
            "skipCount": 0,
            "maxResultCount": 5000,
            "orderType": 1
        }
        res = sendRequest(url, "post", headers=self.puser.headers,
                          js=data, msg="获取收货区域（一级）")
        if res.status_code == 200:
            r = res.json()
            print(f"收货区域查询成功（一级）: {r}")
            self.logger.info(f"收货区域查询成功（一级）: {r}")
            self.receiving_area = [r["full"] for r in r["items"]]
            self.code = 1
            self.status = f"获取收货区域成功（一级）: {self.receiving_area}"
        else:
            print(f"收货区域查询报错（一级）: {res.text}")
            self.logger.info(f"收货区域查询报错（一级）: {res.text}")
            self.code = 0
            self.status = f"收货区域查询报错（一级）: {res.text}"

    def set_reveieving_area(self, region, orderType=1):
        # 设置收货区域
        url = urljoin(self.env.realmName, "carrier-assign-route-rule")
        data = {
            "region": {
                "street": region["street"],
                "city": region["city"],
                "state": region["state"],
                "country": region["country"],
                "zipCode": region["zipCode"],
            },
            "carrierName": "连云港东鑫物流有限公司",
            "carrierCode": "WL221228003",
            "prierCode": 1,
            # 订单类型： 0=未知， 1=提货合约单， 2=提货配送单， 3=产成品自提， 4=副产品自提， 5=副产品双源
            "orderType": orderType,
            # 分配路由码头类型： 0=不是码头， 1=包含码头， 2=仅是码头
            "routeRuleWharfType": 0,
            # # 码头编号
            # "wharfCode": ["MT000266"],
            # # 码头名称
            # "wharfName": ["灌云县测试专用码头"]
        }
        # 水运地址未完成
        res = sendRequest(url, "post", headers=self.puser.headers,
                          js=data, msg="设置收货区域（一级）")
        if res.status_code == 200:
            print(f"收货区域设置成功（一级）: {res.text}")
            self.logger.info(f"收货区域设置成功（一级）: {res.text}")
            self.code = 1
            self.status = "收货区域设置成功（一级）"
        else:
            print(f"收货区域设置报错（一级）: {res.text}")
            self.logger.info(f"收货区域设置报错（一级）: {res.text}")
            self.code = 0
            self.status = "收货区域设置报错（一级）"


class TwoLevelTreatyRule(TreatyRule):
    # 二级合约规则

    def get_treaty_config(self):
        # 获取二级分配路由
        url = urljoin(self.env.realmName,
                      "carrier-assign-route-rule-with-level/config")
        res = sendRequest(url, "get", headers=self.puser.headers,
                          msg="二级合约配置查询")
        if res.status_code == 200:
            r = res.json()
            print(f"二级合约配置查询成功: {r}")
            self.logger.info(f"二级合约配置查询成功: {r}")
            # 不可用,已使用重量进行分配
            self.actualCarrierOrderAllotValue = r["actualCarrierOrderAllotValue"]
            # 订单分配值-实发承运商（如果累计大于这个值，分配下一家承运商）
            self.actualCarrierOrderAllotVehicleCount = r["actualCarrierOrderAllotVehicleCount"]
            # 不可用,已使用重量进行分配
            self.actualCarrierSplitValue = r["actualCarrierSplitValue"]
            # 订单拆分值- 实发承运商拆分重量值（吨）
            self.actualCarrierSplitWeightValue = r["actualCarrierSplitWeightValue"]
            #  启用实发按理重分配；启用则按理重分配，关闭则按捆数分配
            self.enableActualCarrierWeightAllot = r["enableActualCarrierWeightAllot"]
            # 是否启用合约分配路由
            self.enableContractRoute = r["enableContractRoute"]
            self.logger.info(f"是否启用合同单分配路由: {self.enableContractRoute}")
            # 是否启用自提单分配路由
            self.enableProductRoute = r["enableProductRoute"]
            self.logger.info(f"是否启用自提单分配路由: {self.enableProductRoute}")
            # 主承运商分配比例（累积是100）
            self.mainCarrierAllocationRatios = r["mainCarrierAllocationRatios"]
            self.logger.info(
                f"主承运商分配比例: {self.mainCarrierAllocationRatios}")
            # 订单分配值-主承运商(如果累计大于这个值，分配下一家承运商)
            self.mainCarrierOrderAllotValue = r["mainCarrierOrderAllotValue"]
            self.logger.info(f"订单分配值-主承运商: {self.mainCarrierOrderAllotValue}")
            # 主承运商拆分值（捆数）
            self.mainCarrierSplitValue = r["mainCarrierSplitValue"]
            self.code = 1
            self.status = f"获取二级合约配置成功"
        else:
            print(f"二级合约配置查询报错: {res.text}")
            self.logger.info(f"二级合约配置查询报错: {res.text}")
            self.code = 0
            self.status = f"查询二级合约配置报错: {res.text}"

    def set_treaty_config(self, enableContractRoute: bool, enableProductRoute: bool,
                          mainCarrierSplitValue: int, mainCarrierOrderAllotValue: int,
                          actualCarrierOrderAllotValue: int, actualCarrierSplitValue: int,
                          actualCarrierOrderAllotVehicleCount: int, actualCarrierSplitWeightValue: int,
                          enableActualCarrierWeightAllot: bool, mainCarrierAllocationRatios: dict):
        # 设置二级分配路由
        url = urljoin(self.env.realmName,
                      "carrier-assign-route-rule-with-level/set-config")
        data = {
            "enableContractRoute": enableContractRoute,
            "enableProductRoute": enableProductRoute,
            "mainCarrierSplitValue": mainCarrierSplitValue,
            "mainCarrierOrderAllotValue": mainCarrierOrderAllotValue,
            "actualCarrierOrderAllotValue": actualCarrierOrderAllotValue,
            "actualCarrierSplitValue": actualCarrierSplitValue,
            "actualCarrierOrderAllotVehicleCount": actualCarrierOrderAllotVehicleCount,
            "actualCarrierSplitWeightValue": actualCarrierSplitWeightValue,
            "enableActualCarrierWeightAllot": enableActualCarrierWeightAllot,
            "mainCarrierAllocationRatios": mainCarrierAllocationRatios
        }
        res = sendRequest(
            url, "post", headers=self.puser.headers, js=data, msg="二级合约配置设置")
        if res.status_code == 200:
            r = res.json()
            if r["success"] == 1:
                print(f"二级合约配置设置成功: {res.text}")
                self.logger.info(f"二级合约配置设置成功: {res.text}")
                self.code = 1
                self.status = "二级合约配置设置成功"
            else:
                print(f"二级合约配置设置失败: {res.text}")
                self.logger.info(f"二级合约配置设置失败: {res.text}")
                self.code = 0
                self.status = f"二级合约配置设置失败: {res.text}"
        else:
            print(f"二级合约配置设置报错: {res.text}")
            self.logger.info(f"二级合约配置设置报错: {res.text}")
            self.code = 0
            self.status = f"二级合约配置设置报错: {res.text}"

    def get_receiving_area(self):
        # 获取收货区域
        url = urljoin(self.env.realmName,
                      "carrier-assign-route-rule-with-level/search")
        data = {
            "skipCount": 0,
            "maxResultCount": 5000,
            "orderType": 3
        }
        # 发送GET请求，传入headers和请求描述信息
        res = sendRequest(url, "post", headers=self.puser.headers,
                          js=data, msg="收货区域查询（二级）")
        # 判断请求是否成功
        if res.status_code == 200:
            # 解析JSON响应数据
            r = res.json()
            # 打印成功查询的信息
            print(f"收货区域查询成功（二级）: {r}")
            self.logger.info(f"收货区域查询成功（二级）: {r}")
            # 将查询结果存储到实例变量中
            self.code = 1
            self.receiving_area = [item["full"] for item in r["items"]]
        else:
            # 打印错误信息
            print(f"收货区域查询报错（二级）: {res.text}")
            self.logger.info(f"收货区域查询报错（二级）: {res.text}")
            # 设置错误状态信息
            self.code = 0
            self.status = f"收货区域查询报错（二级）: {res.text}"

    def set_reveieving_area(self, region, orderType=1):
        # 设置收货区域
        url = urljoin(self.env.realmName,
                      "carrier-assign-route-rule-with-level")
        data = {
            # 收货区域
            "regionFull": region["full"],
            # 主承运商名称
            "mainCarrierName": "桔子物流公司",
            # 主承运商编码
            "mainCarrierCode": "JZ001",
            # 主承运商优先级
            "mainCarrierPriority": 1,
            # 实发承运商名称
            "actualCarrierName": "JZSF001",
            # 实发承运商编码
            "actualCarrierCode": "桔子实发物流公司",
            # 实发承运商优先级
            "actualCarrierPriority": 1,
            # 每日最多分配捆数
            "maxBundlesPerDay": 0,
            # 每日最多分配理重
            "maxWeightPerDay": 999999,
            # 北港承运单价 - 螺纹
            "beigangPriceRebar": 1234.56,
            # 港承运单价 - 盘螺
            "beigangPriceCoil": 6543.21,
            # 订单类型 0=未知,1=提货合约单,2=提货配送单,3=产成品自提,4=副产品自提,5=副产品双源
            "orderType": 1,
            # 分配路由码头类型 0=不是码头,1=包含码头,2=仅是码头
            # "routeRuleWharfType": 0,
            # # 码头编号
            # "wharfCode": "string",
            # # 码头名称
            # "wharfName": "string"
        }
        res = sendRequest(
            url, "post", headers=self.puser.headers, js=data, msg="收货区域设置（二级）")
        if res.status_code == 200:
            print(f"收货区域设置成功（二级）: {res.text}")
            self.logger.info(f"收货区域设置成功（二级）: {res.text}")
            self.code = 1
            self.status = "收货区域设置成功（二级）"
        else:
            print(f"收货区域设置报错（二级）: {res.text}")
            self.logger.info(f"收货区域设置报错（二级）: {res.text}")
            self.code = 0
            self.status = f"收货区域设置报错（二级）"


class Cargo:
    # 物料信息
    def __init__(self, env: Environment, puser: PcUser, logger: logging.Logger):
        self.code = 0
        self.env = env
        self.puser = puser
        self.logger = logger
        self.cargo_dict = None

    def get_cargo(self):
        # 获取物料信息
        url = urljoin(self.env.realmName, "cargo/search")
        data = {
            "skipCount": 0,
            "maxResultCount": 5000
        }
        res = sendRequest(
            url, "post", headers=self.puser.headers, js=data, msg="物料信息查询")
        if res.status_code == 200:
            r = res.json()
            self.cargo_dict = {
                item["code"]: {
                    # 物料
                    "description": item["description"],
                    # 存货类型
                    "storeTypeName": item["storeTypeName"],
                    # id
                    "id": item["id"]
                } for item in r["items"]
            }
            print(f"物料信息查询成功: {r}")
            self.logger.info(f"物料信息查询成功: {r}")
            self.code = 1
            self.status = f"获取物料数据成功"
        else:
            print(f"物料信息查询报错: {res.text}")
            self.logger.info(f"物料信息查询报错: {res.text}")
            self.code = 0
            self.status = f"物料信息查询报错: {res.text}"

    def set_cargo(self, goods_no: str, unitWeight: str, distributionType: int, type: int, storeType: int, isPrintTakeOrder: bool = False, isPdaUpload: bool = False, isAllowWeighExcess: bool = True):
        # 设置物料信息
        goods_no = self.cargo_dict[goods_no]
        goods_id = goods_no["id"]
        url = urljoin(self.env.realmName, "cargo")

        data = {
            "id": goods_id,
            # 理重
            "unitWeight": unitWeight,
            # 物料类型 10=产成品,20=副产品
            "distributionType": distributionType,
            # 物料类型 10=产成品,20=副产品
            "type": type,
            # 存货类型 10=其他,20=螺纹,30=盘螺,40=钢胚,50=水渣,60=气体
            "storeType": storeType,
            # 是否打印出库单
            # 最后一次过磅使用
            # 辅料 不需要打印出库单
            "isPrintTakeOrder": isPrintTakeOrder,
            # 是否PDA上传
            "isPdaUpload": isPdaUpload,
            # 是否允许过磅超量
            "isAllowWeighExcess": isAllowWeighExcess,
        }
        res = sendRequest(
            url, "put", headers=self.puser.headers, js=data, msg="物料信息设置")
        if res.status_code == 200:
            print(f"物料信息设置成功: {res.text}")
            self.logger.info(f"物料信息设置成功: {res.text}")
            self.code = 1
            self.status = f"物料信息设置成功"
        else:
            print(f"物料信息设置报错: {res.text}")
            self.logger.info(f"物料信息设置报错: {res.text}")
            self.code = 0
            self.status = f"物料信息设置报错"
